/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-09-14 10:12:02
 * @LastEditTime: 2021-10-09 09:56:01
 * @Description:  This files is for f_sdmmc user function definition
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 * 1.0   Zhugengyu   2021/8/6    init
 */
#ifndef BSP_DRIVERS_F_SDMMC_H
#define BSP_DRIVERS_F_SDMMC_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "ft_types.h"
#include "ft_error_code.h"
#include "ft_debug.h"

#define FSDMMC_DEF_BLK_SIZE			512     /* sd/mmc block size */
#define FSDMMC_MAX_BLK_TRANS        8       /* max num of block trans with one read/write cmd, this is becase DMA align buffer is 8 blk */

enum
{
    FSDMMC_DMA_BD_INTR = 0,
    FSDMMC_CMD_INTR,
    FSDMMC_ERROR_INTR,

    FSDMMC_INTR_NUM  
}; /* 中断类型 */

typedef struct
{
    u32 instance_id; /* 控制器id */
    u32 base_addr;   /* 寄存器基地址 */
    u32 irq_num[FSDMMC_INTR_NUM]; /* 控制器中断号 */
    boolean enable_irq[FSDMMC_INTR_NUM]; /* 中断开关 */
    u32 irq_priority[FSDMMC_INTR_NUM]; /* 中断优先级 */
    const char *irq_name[FSDMMC_INTR_NUM]; /* 中断名 */
} FSdmmcConfig;

typedef void (*FSdmmcIntrHandler)(s32 vector, void *host_p);

typedef struct
{
    FSdmmcConfig config; /* 控制器配置 */
    u32 is_ready; /* 控制器初始化完成标志 */
    FSdmmcIntrHandler intr_handler[FSDMMC_INTR_NUM]; /* 中断处理函数 unused */
} FSdmmcCtrl;

/**
 * @name: FSdmmcLookupConfig
 * @msg: 获取SDMMC控制器默认配置
 * @return {*}
 * @param {u32} instance_id
 */
const FSdmmcConfig *FSdmmcLookupConfig(u32 instance_id);
/**
 * @name: FSdmmcInitialize
 * @msg: 初始化SDMMC控制器
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p, sdmmc控制块
 * @param {FSdmmcConfig} *config_p, sdmmc输入配置
 */
u32 FSdmmcInitialize(FSdmmcCtrl *ctrl_p, const FSdmmcConfig *config_p);

/**
 * @name: FSdmmcDeInitialize
 * @msg: 去初始化SDMMC控制器
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p
 */
void FSdmmcDeInitialize(FSdmmcCtrl *ctrl_p);
/**
 * @name: FSdmmcInitIntr
 * @msg: 初始化SDMMC控制器的中断配置
 * @return {*}
 * @param {FSdmmcCtrl} *host_p
 */
u32 FSdmmcInitIntr(FSdmmcCtrl *host_p);
/**
 * @name: FSdmmcGetIntrMask
 * @msg: 获取SDMMC控制器的中断掩码位
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p
 * @param {u32} intr_type
 */
u32 FSdmmcGetIntrMask(FSdmmcCtrl *ctrl_p, u32 intr_type);
/**
 * @name: FSdmmcSetIntrMask
 * @msg: 设置SDMMC控制器的中断掩码位
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p
 * @param {u32} intr_type
 * @param {u32} mask
 * @param {boolean} enable
 */
void FSdmmcSetIntrMask(FSdmmcCtrl *ctrl_p, u32 intr_type, u32 mask, boolean enable);
/**
 * @name: FSdmmcSetCardClk
 * @msg: 设置sdmmc卡时钟频率
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p, sdmmc控制块
 * @param {u32} clk_freq_khz, sdmmc卡频率
 */
u32 FSdmmcSetCardClk(FSdmmcCtrl *ctrl_p, u32 clk_freq_khz);
/**
 * @name: FSdmmcDetectCard
 * @msg: 检测SDMMC卡是否在位
 * @return {*} TRUE: 卡在位， FALSE: 卡不在位
 * @param {FSdmmcCtrl} *ctrl_p
 */
boolean FSdmmcDetectCard(FSdmmcCtrl *ctrl_p);
/**
 * @name: FSdmmcResetWriteDMA
 * @msg: reset sdmmc read DMA
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p, sdmmc控制块
 * @param {uintptr} card_addr, sdmmc设备地址
 * @param {u32} blk_cnt, sdmmc设备块索引
 * @param {u8} *buf_p, 写源地址
 */
void FSdmmcResetReadDMA(FSdmmcCtrl *ctrl_p, uintptr card_addr, u32 blk_cnt, const u8 *buf_p);
/**
 * @name: FSdmmcResetWriteDMA
 * @msg: reset sdmmc write DMA
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p, sdmmc控制块
 * @param {uintptr} card_addr, sdmmc设备地址
 * @param {u32} blk_cnt, sdmmc设备块索引
 * @param {u8} *buf_p, 写源地址
 */
void FSdmmcResetWriteDMA(FSdmmcCtrl *ctrl_p, uintptr card_addr, u32 blk_cnt, const u8 *buf_p);
/**
 * @name: FSdmmcStartCmd
 * @msg: 发送命令和命令参数
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p
 * @param {u32} cmd
 * @param {u32} arg
 */
void FSdmmcStartCmd(FSdmmcCtrl *ctrl_p, u32 cmd, u32 arg);
/**
 * @name: FSdmmcWaitCmdEnd
 * @msg: 阻塞等待命令执行完成
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p
 */
u32 FSdmmcWaitCmdEnd(FSdmmcCtrl *ctrl_p);
/**
 * @name: FSdmmcWaitDataEnd
 * @msg: 阻塞等待数据传输完成
 * @return {*}
 * @param {FSdmmcCtrl} *ctrl_p
 * @param {boolean} read
 */
u32 FSdmmcWaitDataEnd(FSdmmcCtrl *ctrl_p, boolean read);


#define FSDMMC_SUCCESS          FT_SUCCESS  
#define FSDMMC_ERR_NOT_READY    FT_MAKE_ERRCODE(ErrModBsp, ErrBspMmc, BIT(0))
#define FSDMMC_ERR_TIMEOUT      FT_MAKE_ERRCODE(ErrModBsp, ErrBspMmc, BIT(1))
#define FSDMMC_ERR_CMD_FAILED   FT_MAKE_ERRCODE(ErrModBsp, ErrBspMmc, BIT(2))
#define FSDMMC_ERR_DATA_FAILED  FT_MAKE_ERRCODE(ErrModBsp, ErrBspMmc, BIT(3))

#define FSDMMC_DEBUG_TAG "FSDMMC"
#define FSDMMC_ERROR(format, ...)   FT_DEBUG_PRINT_E(FSDMMC_DEBUG_TAG, format, ##__VA_ARGS__)
#define FSDMMC_INFO(format, ...)    FT_DEBUG_PRINT_I(FSDMMC_DEBUG_TAG, format, ##__VA_ARGS__)
#define FSDMMC_DEBUG(format, ...)   FT_DEBUG_PRINT_D(FSDMMC_DEBUG_TAG, format, ##__VA_ARGS__)

#define FSDMMC_TIMEOUT                500  /* timeout for retries */

#ifdef __cplusplus
}
#endif

#endif